// 本文件为通用js方法

/**
 * 防抖函数  (指定时间内只执行一次,期间触发不会执行,且重新计时。类似电梯上人,有人在指定时间内按开门就永远关不上)
 * @param fn 需要执行的函数
 * @param delay 延迟时间
 * @returns {Function}
 */
export function debounce(fn: (...args: any[]) => void, delay: number) {
    let timer: number | null = null;
    return (...args: any[]) => {
        if (!timer) {
            timer = window.setTimeout(() => {
                fn(...args);
                timer = null;
            }, delay);
        }
    };
}

/**
 * 节流函数  (指定时间内只执行一次,期间触发不执行,过了延时时间触发再执行。类似打点滴)
 * @param fn 需要执行的函数
 * @param delay 延迟时间
 * @returns {Function}
 */
export function throttle(fn: (...args: any[]) => void, delay: number) {
    let oldTime: number = 0;
    return (...args: any[]) => {
        let newTime = Date.now(); // 当前时间戳

        // 操作间隔大于延迟时间，执行函数，并更新时间戳
        if (newTime - oldTime > delay) {
            fn(...args);
            oldTime = newTime;
        }
    };
}

/**
 * 深拷贝 (完整兼容可以使用loadsh库的cloneDeep方法)
 * @param obj 需要拷贝的对象
 * @return {any} 拷贝后的对象
 * */
export function deepClone(obj: any): any {
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }

    if (obj instanceof Date) {
        return new Date(obj);
    }

    if (obj instanceof Array) {
        const arr = [];
        for (let i = 0; i < obj.length; i++) {
            arr.push(deepClone(obj[i]));
        }
        return arr;
    }

    if (obj instanceof Object) {
        const o: anyObj = {};
        for (const key in obj) {
            if (obj.hasOwnProperty(key)) {
                o[key] = deepClone(obj[key]);
            }
        }
        return o;
    }
}

/**
 * 获取数字小数位数
 */
const getDecimalDigits = (num: number): number => {
    const str = num.toString();
    return str.includes('.') ? str.split('.')[1].length : 0;
};

/**
 * js数学运算精度问题 (完整兼容可使用Decimal.js等库)
 * @param num1
 * @param num2
 * @param type add:加法,sub:减法,mul:乘法,div:除法
 * @return {number}
 * */
export function preciseMath(num1: number, num2: number, type: 'add' | 'sub' | 'mul' | 'div'): number {
    const digits1 = getDecimalDigits(num1);
    const digits2 = getDecimalDigits(num2);
    const base = Math.pow(10, Math.max(digits1, digits2)); // 10的n次方，n为小数位数最大值

    switch (type) {
        case 'add':
            return (Math.round(num1 * base) + Math.round(num2 * base)) / base;
        case 'sub':
            return (Math.round(num1 * base) - Math.round(num2 * base)) / base;
        case 'mul': {
            const adjust = Math.pow(10, digits1 + digits2);
            return (Math.round(num1 * Math.pow(10, digits1)) * Math.round(num2 * Math.pow(10, digits2))) / adjust;
        }
        case 'div': {
            const numerator = Math.round(num1 * base);
            const denominator = Math.round(num2 * base);
            if (denominator === 0) throw new Error('Division by zero');
            return numerator / denominator;
        }

        default:
            throw new Error('Unsupported operation type');
    }
}

/**       下面是定义的接口，给上面的函数用            **/

interface anyObj {
    [key: string]: any; // 允许任意字符串key，任意类型value
}
